export type ResolveType<TR> = (value: TR | PromiseLike<TR>) => void
export default class DebounceHelper<TP, TR> {
	private dataQueue: TP[] = []
	private resolveQueue: ResolveType<TR>[] = []
	private timeoutId: NodeJS.Timeout | null = null
	private wait: number = 100
	private handler: (params: TP[]) => Promise<TR>

	constructor(params: { wait?: number; handler: (params: TP[]) => Promise<TR> }) {
		this.wait = params.wait ? params.wait : this.wait
		this.handler = params.handler
	}

	// 获取防抖函数
	getDebounceDefine = (): ((params: TP) => Promise<TR>) => {
		const self = this

		const func = (params: TP): Promise<TR> => {
			if (self.timeoutId) {
				clearTimeout(self.timeoutId!)
			}
			self.dataQueue.push(params)
			const promise: Promise<TR> = new Promise<TR>(resolve => {
				self.resolveQueue.push(resolve)
				self.timeoutId = setTimeout(() => {
					const dataQueue = self.getDataQueueAndClear()
					const resolveQueue = self.getResolveQueueAndClear()
					self.handlerWrapper(dataQueue, resolveQueue)
				}, self.wait)
			})

			return promise
		}

		return func
	}

	private getDataQueueAndClear = (): TP[] => {
		const self = this
		const data = self.dataQueue
		self.dataQueue = []
		return data
	}

	private getResolveQueueAndClear = (): ResolveType<TR>[] => {
		const self = this
		const resolveQueue = self.resolveQueue
		self.resolveQueue = []
		return resolveQueue
	}

	private handlerWrapper = (dataQueue: TP[], resolveQueue: ResolveType<TR>[]): void => {
		this.handler(dataQueue).then(value => {
			resolveQueue.forEach(resolve => {
				resolve(value)
			})
		})
	}
}
